package com.gzzjwd.mklink.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 文件处理工具类
 * @Author: wyx
 * @Date: 2023/8/20 12:22
 */
public class FileUtil extends cn.hutool.core.io.FileUtil {
    
    /**
     * 验证路径是否正确盘符路径
     * @param path
     * @return
     */
    public static boolean validPath(String path){
         if(StrUtil.isNotEmpty(path)){
            if(path.indexOf(":\\")>-1){
                return true;
            }
         }
         return false;
    }
    
    /**
     * 判断是否是软链接
     * @param file
     * @return
     * @throws IOException
     */
    public static boolean isLink(File file) throws IOException {
        if (file == null) {
            throw new NullPointerException("File must not be null");
        }
        Path path = file.toPath().toRealPath();
        return !path.equals(file.toPath());
    }
    
    /**
     * 将解压出来的文件还原回去
     * @param sourcePath 源路径
     * @param targetFile 需要移动的文件
     * @return
     */
    public static boolean moveFile(String sourcePath,String targetPath,List<File> targetFile){
        /**
         * corePoolSize： 一直保持的线程的数量，即使线程空闲也不会释放。除非设置了 allowCoreThreadTimeout 为 true；
         * maxPoolSize：允许最大的线程数，队列满时开启新线程直到等于该值；
         * keepAliveTime：表示空闲线程的存活时间。当线程空闲时间达到keepAliveTime，该线程会退出，直到线程数量等于corePoolSize。只有当线程池中的线程数大于corePoolSize时keepAliveTime才会起作用，直到线程中的线程数不大于corepoolSIze；
         * TimeUnitunit：表示keepAliveTime的单位；
         * workQueue：缓存任务的队列；
         * handler：表示当 workQueue 已满，且池中的线程数达到 maxPoolSize 时，线程池拒绝添加新任务时采取的策略。
         */
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(20, 50, 4, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolExecutor.AbortPolicy());
        //大集合拆分成N个小集合，保证多线程异步执行, 过大容易回到单线程
        List<List<File>> splitNList = split(targetFile, 1000); //先设置100  100以内不考虑性能
        // 记录单个任务的执行次数
        CountDownLatch countDownLatch = new CountDownLatch(splitNList.size());
        long startTime = System.currentTimeMillis();
        for (List<File> singleList : splitNList) {
            // 线程池执行
            threadPool.execute(new Thread(() -> {
                for (File file : singleList) {
                    //统一赋值方法
                    String fileName = file.getPath();
                    fileName = fileName.replace(targetPath,sourcePath);
                    //System.out.println("源路径："+file.getPath()+"目标路径："+fileName);
                    File destFile = new File(fileName);
                    try {
                        FileUtil.move(file,destFile,true);
                    }catch (Exception e){
                       //这里当文件被占用时候会进来：不用管
                    }
                    countDownLatch.countDown();
                }
            }));
        }
        try {
            countDownLatch.await();
            long endTime = System.currentTimeMillis();
            //System.out.println("线程数为{}的线程池插入"+countDownLatch.getCount()+"用时:{}"+threadPool.getPoolSize()+"||"+(endTime - startTime));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return true;
    }
    
    /**
     * 这里使用泛型T 接收  做到通用工具类
     * esList总数据List  subListLength:需要切割的长度
     */
    public static <T> List<List<T>> split(List<T> resList, int subListLength) {
        
        if (CollectionUtil.isEmpty(resList) || subListLength <= 0) {
            return new ArrayList<>();
        }
        List<List<T>> ret = new ArrayList<>();
        int size = resList.size();
        if (size <= subListLength) {  //指定数据过小直接处理
            ret.add(resList);
        } else {
            int n = size / subListLength;
            int last = size % subListLength;
            // 分成n个集合，每个大小都是 subListLength 个元素
            for (int i = 0; i < n; i++) {
                List<T> itemList = new ArrayList<>();
                for (int j = 0; j < subListLength; j++) {
                    itemList.add(resList.get(i * subListLength + j));
                }
                ret.add(itemList);
            }
            // last的进行处理
            if (last > 0) {
                List<T> itemList = new ArrayList<>();
                for (int i = 0; i < last; i++) {
                    itemList.add(resList.get(n* subListLength + i));
                }
                ret.add(itemList);
            }
        }
        return ret;
    }
}
